// Menu items
var executeMenuItem = null;

// Menu id's
var CMD_EXECUTE = 10;
var CMD_SET_WRONG_URL = 11;
var CMD_SET_DETAILS = 12;

window.onload = init;

// Other than OK status overrides the default status obtained from window.navigator.onLine
var CONNECTION_STATUS_UNUSED = -1;
var CONNECTION_STATUS_UNINITIALIZED = 0;
var CONNECTION_STATUS_REQUEST_INITED = 1; // When the connection is initialised
var CONNECTION_STATUS_CONNECTING = 2; // When the connection is sent
var CONNECTION_STATUS_OK = 3; // Use the window.navigator.onLine to decide the status
var CONNECTION_STATUS_FAILED = 4; // When the connection request fails
var CONNECTION_STATUS_NOT_ALLOWED = 5; // When the connection is disabled
var CONNECTION_STATUS_HANDLING_ERROR = 6; // Parsing errors etc.

// Connection status information  
var connectionStatus = CONNECTION_STATUS_UNINITIALIZED;

var fetchURL = "http://www.forum.nokia.com/feeds.html?file=recently_published.rss";

// XMLHttpRequest object
var requestObject = null;

// Flag that tracks whether we want to show when the widget is in transitional states or not.
// The transitional states are CONNECTION_STATUS_REQUEST_INITED and
// CONNECTION_STATUS_CONNECTING.
var showDetails = true;


// Initializes the widget
function init() {
	debug('init');
	if (window.widget) {
	    createMenu();
	}
	
	initOnonlineAndOnoffline();
	
	// Let's update the connection status and status info...
	var newConnectionStatus = CONNECTION_STATUS_OK;
	updateStatusInfo(newConnectionStatus);
}

// Creates the main menu
function createMenu() {
    executeMenuItem = new MenuItem("Execute snippet", CMD_EXECUTE);
    executeMenuItem.onSelect = onMenuItemSelected;
    window.menu.append(executeMenuItem);

    executeMenuItem = new MenuItem("Toggle URL", CMD_SET_WRONG_URL);
    executeMenuItem.onSelect = onMenuItemSelected;
    window.menu.append(executeMenuItem);

    executeMenuItem = new MenuItem("Toggle details", CMD_SET_DETAILS);
    executeMenuItem.onSelect = onMenuItemSelected;
    window.menu.append(executeMenuItem);
}

// Gets called when a menu item is selected
function onMenuItemSelected(menuId) {
    switch (menuId) {
        case CMD_EXECUTE:
            executeSnippet();
            break;
        case CMD_SET_WRONG_URL:
            toggleWrongURL();
            break;
        case CMD_SET_DETAILS:
            toggleShowDetails();
            break;
		default: {
			alert('unknown menu item: '+menuId);
		}
    }
}

// Executes the snippet.
// If showDetails is true, sets the connectionStatus to be 
// CONNECTION_STATUS_REQUEST_INITED and updates the icon of the status.
// Sets the timeout to call the sendRequest function after 1 second.
function executeSnippet() {
    if (showDetails) {
		var newConnectionStatus = CONNECTION_STATUS_REQUEST_INITED;
		updateStatusInfo(newConnectionStatus);
    }
	else {
		// Don't update anything
	}
	debug('Initializing request');
	
	setTimeout(sendRequest,1000);
}

function toggleWrongURL() {
	if (fetchURL == "http://qqq.nokia.com") {
		fetchURL = "http://www.forum.nokia.com/feeds.html?file=recently_published.rss";
		alert("feed URL was set to correct URL")
	}
	else {
		fetchURL = "http://qqq.nokia.com";
		alert("feed URL was set to fake URL")
	}
}

function toggleShowDetails() {
	if (showDetails) {
		showDetails = false;
		alert("Now the transitional states are NOT shown during the update");
	}
	else {
		showDetails = true;
		alert("The transitional states are shown during the update");
	}
}

// Initializes ononline and onoffline functions to change the status if needed
function initOnonlineAndOnoffline() {
	window.onoffline = function(){
		if(requestObject == null) {
			// update the status only if there is no existing fetch request
			var newConnectionStatus = CONNECTION_STATUS_NOT_ALLOWED;
			updateStatusInfo(newConnectionStatus);
		}
		else {
			// else the existing fetch request updates the status
			debug('Set to Offline, request is in progress');
		}
	};
	window.ononline = function() {
		if(requestObject == null) {
			debug('Set to Online, updating status');
			// update the status only if there is no existing fetch request
			var newConnectionStatus = CONNECTION_STATUS_OK;
			updateStatusInfo(newConnectionStatus);
		}
		else {
			// else the existing fetch request updates the status
			debug('Set to Online, request is in progress');
		}
	}
}


// Processes request
function sendRequest() {
	debug('Sending request');

    // check if the fetchURL is valid and there's no update currently in progress
    if ((fetchURL != null)
        && (requestObject == null)) {
		// Shortcut to return if in offline mode
		if (window.widget && (typeof window.navigator.onLine=='number')) {
			if (window.navigator.onLine == window.navigator.NetworkNotAllowed) {
				var newConnectionStatus = CONNECTION_STATUS_NOT_ALLOWED;
				updateStatusInfo(newConnectionStatus);
			    releaseResources();
				debug("Widget is offline, can not send the request!");
				return;
			}
		}
			
        // show progress information if this is a commanded feed update
        if (showDetails) {
			var newConnectionStatus = CONNECTION_STATUS_CONNECTING;
    		updateStatusInfo(newConnectionStatus);
        } 
		
        // fetch the specified URL
        requestObject = new AjaxThing();
        var url = fetchURL;
		// Note that each url will be different, thus they are not cached.
        url=url+"&sid="+Math.random();
        requestObject.onreadystatechange=stateChanged;
        requestObject.open("GET",url,true);
        requestObject.send(null);

		debug("Request sent...");
    }
}

// Called when the asynchronous ajax response is obtained
function stateChanged() {
	if (requestObject.readyState == 4) {
		var responseStatus = null;
		try {
			responseStatus = requestObject.status
		}
		catch (e) {
		}
		fetchCompleted(responseStatus);
	}
}


// Callback function that gets called when the fetching has completed.
function fetchCompleted(responseStatus) {
	var newConnectionStatus = CONNECTION_STATUS_UNUSED;
	
	if (responseStatus == 200) {
		newConnectionStatus = CONNECTION_STATUS_OK;
		
		/* Here: get the response from the requestObject, handle it and
		 * possibly set the newConnectionStatus to be some failure state
		 * like newConnectionStatus = CONNECTION_STATUS_HANDLING_ERROR; 
		 */
		
		debug("Response was handled.");
    } else {
		// We could notice here that the connection is disabled, i.e.,
		// the short cut of sendRequest is not working when the user denies the
		// connection when asked for the first time.
		if (window.widget && (typeof window.navigator.onLine == 'number')) {
			switch (window.navigator.onLine) {
				case window.navigator.NetworkNotAllowed:
				{
					newConnectionStatus = CONNECTION_STATUS_NOT_ALLOWED;
					break;
				}
				// If the network access is allowed, there could be another reason
				// for the error, e.g., wrong URL address. Check them here.
				case window.navigator.NetworkAccessAllowed:
				case window.navigator.NetworkAccessible:
				{
					newConnectionStatus = CONNECTION_STATUS_FAILED;
					break;
				}
			}
		}
		else {
			newConnectionStatus = CONNECTION_STATUS_FAILED;
		}
		debug("Error in the connection!");
    }
	
	// Now the response is handled. Update the status and release the resources
	updateStatusInfo(newConnectionStatus);
    releaseResources();
}

// Called after the current request process has ended.
function releaseResources() {
    // null the requestObject reference to indicate that there's no current
	// request in progress
    requestObject = null;
}

// Updates the status icon
function updateStatusInfo(newConnectionStatus) {
	connectionStatus = newConnectionStatus;
	var spanClass = '';
	switch (connectionStatus) {
		case CONNECTION_STATUS_OK:{
			if (window.widget && (typeof window.navigator.onLine == 'number')) {
				switch (window.navigator.onLine) {
					case window.navigator.NetworkAccessAllowed:
					{
						spanClass = 'normal';
						break;
					}
					case window.navigator.NetworkAccessible:
					{
						spanClass = 'active';
						break;
					}
					case window.navigator.NetworkNotAllowed:
					{
						spanClass = 'disabled';
						break;
					}
					default:
					{
						spanClass = '';
					}
				}
			}
			else {
				spanClass = 'active';
			}
			break;
		}
		case CONNECTION_STATUS_CONNECTING: {
			spanClass = 'connecting';
			break;
		}
		case CONNECTION_STATUS_REQUEST_INITED:{
			spanClass = 'waiting';
			break;
		}
		case CONNECTION_STATUS_HANDLING_ERROR:{
			spanClass = 'error-handling';
			break;
		}
		case CONNECTION_STATUS_FAILED:{
			spanClass = 'error-failed';
			break;
		}
		case CONNECTION_STATUS_NOT_ALLOWED: {
			spanClass = 'disabled';
			break;
		}
		default : {
			spanClass = '';
		}
	}
	var i;
	debug('status="'+spanClass+ '", connectionStatus:'+connectionStatus
	      + ', onLine:'+window.navigator.onLine);
	spanClass = 'status-icon '+spanClass;
	document.getElementById('statusIcon').setAttribute('class', spanClass);
}
